package com.hbnu.system.core.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hbnu.system.core.model.dto.BaseTreeEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Bean工具类
 *
 * @author liyan
 */
@Service("beanService")
public class BeanServiceImpl implements IBeanService {

    /**
     * 转换类型E实例集合，至类型T
     * 测试 1000个对象，使用New对象方式转换50ms左右；
     * 使用newInstance方法，花费150ms左右，时间差距为3倍
     *
     * @param sources     实例集合源
     * @param targetClass 目标对象
     * @return 对象T集合
     */
    @Override
    public <T, E> List<T> copyListProperties(List<E> sources, Class<T> targetClass) {

        if (CollectionUtils.isEmpty(sources)) {
            return Collections.emptyList();
        }

        return sources.stream().map(m -> {
            T target;
            try {
                target = targetClass.newInstance();
                BeanUtil.copyProperties(m, target);
            } catch (Exception e) {
                throw new ClassCastException("cast " + targetClass + "fail.");
            }
            return target;
        }).collect(Collectors.toList());
    }

    @Override
    public <T, E> List<T> copyListProperties(List<E> sources, Class<T> targetClass, String... ignoreProperties) {
        if (CollectionUtils.isEmpty(sources)) {
            return Collections.emptyList();
        }

        return sources.stream().map(m -> {
            T target;
            try {
                target = targetClass.newInstance();
                BeanUtil.copyProperties(m, target, ignoreProperties);
            } catch (Exception e) {
                throw new ClassCastException("cast " + targetClass + "fail.");
            }
            return target;
        }).collect(Collectors.toList());
    }


    @Override
    public <R extends BaseTreeEntity<R>> List<R> buildTree(List<R> nodes) {
        if (CollectionUtil.isEmpty(nodes)) {
            return Collections.emptyList();
        }
        // 根据parentId分组子节点
        Map<String, List<R>> sub = nodes.stream().filter(node -> node.getParentId() != null && Long.parseLong(node.getParentId()) > 0L)
                .collect(Collectors.groupingBy(BaseTreeEntity::getParentId));
        nodes.forEach(node -> node.setChildren(sub.get(node.getId())));
        return nodes.stream().filter(node -> node.getParentId() == null || Long.parseLong(node.getParentId()) <= 0).collect(Collectors.toList());
    }

//    @Override
//    public <R extends BaseTreeEntity<R>> List<R> buildTree(List<R> nodes) {
//        if (CollectionUtil.isEmpty(nodes)) {
//            return Collections.emptyList();
//        }
//        // 根据parentId分组子节点
//        Map<Integer, List<R>> sub = nodes.stream().filter(node -> node.getParentId() != null && node.getParentId() > 0)
//                .collect(Collectors.groupingBy(BaseTreeEntity::getParentId));
//        nodes.forEach(node -> node.setChildren(sub.get(node.getId())));
//        return nodes.stream().filter(node -> node.getParentId() == null || node.getParentId() <= 0).collect(Collectors.toList());
//    }

    /**
     * 得到类型T的属性结构
     *
     * @param sourceData 必须实现BaseTreeEntity
     * @return 树形结构R
     */
    @Override
    public <R extends BaseTreeEntity<R>> List<R> getTree(List<R> sourceData) {

        if (CollectionUtil.isEmpty(sourceData)) {
            return Collections.emptyList();
        }

        boolean parentClass = sourceData.get(0).getClass().getSuperclass().equals(BaseTreeEntity.class);
        if (!parentClass) {
            throw new RuntimeException("class " + sourceData.get(0).getClass() + " not subclass BaseTreeEntity.class");
        }
        List<R> trees = new ArrayList<>();
        for (R treeNode : sourceData) {
            // 找到最顶层的父级节点
            if (Integer.parseInt(treeNode.getId()) == 0 || null == treeNode.getParentId()) {
                trees.add(findChildren(treeNode, sourceData));
            }
        }
        return trees;
    }

    @Override
    public <T, E> IPage<T> copyPageProperties(IPage<E> sources, Class<T> targetClass) {
        IPage<T> targetPage = new Page<>();
        BeanUtil.copyProperties(sources, targetPage, "records");
        List<E> records = sources.getRecords();
        List<T> targetRecords = copyListProperties(records, targetClass);
        return targetPage.setRecords(targetRecords);
    }

    /**
     * 递归查找地址子节点
     *
     * @param treeNode  子节点
     * @param treeNodes 父节点
     * @return 子节点
     */
    private <R extends BaseTreeEntity<R>> R findChildren(R treeNode, List<R> treeNodes) {
        for (R it : treeNodes) {
            if (treeNode.getId().equals(it.getParentId())) {
                if (treeNode.getChildren() == null) {
                    treeNode.setChildren(new ArrayList<>());
                }
                treeNode.getChildren().add(findChildren(it, treeNodes));
            }
        }
        return treeNode;
    }
}
